Skip to main content

Data Types

Inferred

An inferred data type means Go figures out the variable’s type automatically from the value you give it — you don’t have to write the type yourself.

When you use the short declaration syntax:

name := "Alice"
  • You didn’t say string anywhere.
  • Go sees "Alice" is text in quotes → infers type = string.

Why it’s possible

  • Go is statically typed (types are fixed at compile time), but the compiler is smart enough to detect the type from the value.
  • This only works when you assign a value immediately.

What happens if you don’t give a value?

x :=     // ❌ ERROR: missing value
  • Go must have a value to infer the type.
  • If you want an empty variable, you must use var and specify the type:
var x int

Once inferred, type is fixed

Even if Go inferred the type for you, it’s still fixed:

count := 10     // int
count = "ten" // ❌ ERROR: cannot assign string to int

Common values and the types Go infers for them when you use :=:

ValueInferred TypeExplanation
42intWhole number → integer type
3.14float64Decimal number → 64-bit float
"Hello"stringText in quotes → string
truebooltrue or false → boolean
'a'runeSingle quotes → rune (Unicode char)
[]int{1, 2, 3}[]intSlice (list) of integers
map[string]int{"a": 1}map[string]intMap with string keys and int values

Example of inferred

func main() {
x := 42 // int
y := 3.14 // float64
s := "Hello" // string
b := true // bool
c := 'a' // rune
arr := []int{1,2} // slice of int
m := map[string]int{"a": 1}

fmt.Printf("%T %T %T %T %T %T %T\n", x, y, s, b, c, arr, m)
}

Primitive Data Types

1. Numbers

Integers

  • Whole numbers, no decimal point.
  • Two forms: signed (can be negative) and unsigned (only positive).
TypeSize (bits)Range Example
intplatform-dependent (32 or 64 bits)Large range for general use
int88 bits-128 to 127
int1616 bits-32,768 to 32,767
int3232 bits-2,147,483,648 to 2,147,483,647
int6464 bitsVery large range
uint88 bits0 to 255 (alias: byte)
uint1616 bits0 to 65,535
uint3232 bits0 to 4,294,967,295
uint6464 bits0 to very large

Floating Point Numbers

  • Numbers with decimals.
TypeSize (bits)Range / Precision
float3232 bits~6 decimal digits
float6464 bits~15 decimal digits (default)

Complex Numbers

  • Numbers with a real and imaginary part.
TypeExample
complex641 + 2i (real: float32, imaginary: float32)
complex1283 + 4i (real: float64, imaginary: float64)

2. Text

String

  • Sequence of characters inside double quotes " ".
  • Immutable (cannot be changed after creation).
var name string = "Masum"
fmt.Println(name)

Rune

  • Represents a single Unicode character.
  • Stored as an int32.
var letter rune = 'A'
fmt.Println(letter) // prints Unicode code point 65

Composite Data Types

1. Array

  • Fixed-size list of elements of the same type.
var numbers [3]int = [3]int{1, 2, 3}

2. Slice

  • Like an array, but size can change.
fruits := []string{"Apple", "Banana", "Cherry"}

3. Map

Key-value pairs (like a dictionary).

scores := map[string]int{"Alice": 90, "Bob": 85}

4. Struct

Groups different fields into one object.

type Person struct {
name string
age int
}

Interface and Special Types

  • Interface: Defines behavior without implementation.
  • Pointer: Stores memory address of a value.
  • Nil: Zero value for pointers, maps, slices, etc.

Example of Data Types

package main

import "fmt"

func main() {
// Basic types
var age int = 25
var pi float64 = 3.14
var name string = "Alice"
var isActive bool = true

// Composite
fruits := []string{"Apple", "Banana"}
scores := map[string]int{"Bob": 80, "Eve": 95}

fmt.Println(age, pi, name, isActive)
fmt.Println("Fruits:", fruits)
fmt.Println("Scores:", scores)
}

Output:

25 3.14 Alice true
Fruits: [Apple Banana]
Scores: map[Bob:80 Eve:95]

struct

In Go, a struct is a composite data type that groups together zero or more fields (variables) under a single name. It’s similar to classes in object-oriented languages, but structs don’t have methods directly—instead, you can attach methods to them separately.

Key Features of Struct in Go

  1. User-defined type – lets you define your own data model.
  2. Collection of fields – each with a name and type.
  3. Zero-value initialization – all fields get a default value (e.g., 0 for int, "" for string).
  4. Pass by value – when assigning or passing, the struct gets copied (unless you use pointers).
  5. Supports methods – you can attach methods to structs (like OOP classes).
  6. Anonymous fields & embedding – allows inheritance-like behavior.
  7. Nested struct – struct inside another struct.

Example of Basic struct

package main

import "fmt"

// Define a struct
type Person struct {
Name string
Age int
City string
}

func main() {
// 1. Create struct with field names
p1 := Person{Name: "Masum", Age: 24, City: "Dhaka"}

// 2. Create struct without specifying field names (order matters)
p2 := Person{"Ayesha", 22, "Chittagong"}

// 3. Zero-value struct
var p3 Person // all fields empty: "" and 0
p3.Name = "Rahim"
p3.Age = 30
p3.City = "Sylhet"

fmt.Println(p1) // {Masum 24 Dhaka}
fmt.Println(p2) // {Ayesha 22 Chittagong}
fmt.Println(p3) // {Rahim 30 Sylhet}
}

Nested Structs

package main

import "fmt"

type Address struct {
City string
Street string
}

type Student struct {
Name string
Age int
Address Address // nested struct
}

func main() {
s := Student{
Name: "Masum",
Age: 24,
Address: Address{
City: "Dhaka",
Street: "Banani",
},
}

fmt.Println(s.Name, "lives in", s.Address.City)
}

Anonymous & Embedded Structs (like inheritance)

package main

import "fmt"

type Person struct {
Name string
Age int
}

// Embedded struct
type Employee struct {
Person // inherits fields of Person
EmployeeID string
}

func main() {
e := Employee{
Person: Person{Name: "Masum", Age: 24},
EmployeeID: "EMP123",
}

// Direct access (because of embedding)
fmt.Println(e.Name) // Masum
fmt.Println(e.EmployeeID) // EMP123
}